package org.maxgroundstation.groundstation.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.util.Iterator;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;

import org.maxgroundstation.groundstation.GroundStation;
import org.maxgroundstation.groundstation.GroundStationEvent;
import org.maxgroundstation.groundstation.GroundStationListener;
import org.maxgroundstation.groundstation.comm.service.Service;
import org.maxgroundstation.groundstation.comm.service.ServiceEvent;
import org.maxgroundstation.groundstation.comm.service.ServiceListener;
import org.maxgroundstation.groundstation.comm.service.log.LogService;

/**
 * A panel for viewing logs.
 * @author Scott Davis
 * 
 * Copyright (C) 2010  Scott Davis
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@SuppressWarnings("serial")
public class LogPanel extends JPanel implements GroundStationListener, ServiceListener {
    
    // Static values.
    private static final int MAX_LINES_DISPLAYED = 1000;
    
    // Data members.
    private JScrollPane scrollPanel;
    private Document textDoc;
    
    /**
     * Constructor
     * @param gs the ground station.
     */
    public LogPanel(GroundStation gs) {
        super();
        
        // Set background color to white.
        setOpaque(true);
        setBackground(Color.WHITE);
        
        // Set the layout.
        setLayout(new BorderLayout());
        
        // Create scroll panel.
        scrollPanel = new JScrollPane();
        add(scrollPanel, BorderLayout.CENTER);
        
        // Create text panel.
        JTextArea textPanel = new JTextArea();
        textPanel.setEditable(false);
        scrollPanel.setViewportView(textPanel);
        textDoc = textPanel.getDocument();
        
        // Register as ground station listener.
        gs.addGroundStationListener(this);
    }

    @Override
    public void groundStationUpdate(GroundStationEvent event) {
        // If services initialized from robot, check for log service.
        if (GroundStationEvent.SERVICES_INITIALIZED.equals(event.getType())) {
            GroundStation gs = (GroundStation) event.getSource();
            Iterator<Service> i = gs.getServiceComm().getServices().iterator();
            while (i.hasNext()) {
                Service service = i.next();
                
                // Subscribe to log service.
                if (service.getID().equalsIgnoreCase(LogService.SERVICE_ID)) {
                    service.addServiceListener(this);
                }
            }
        }
    }
    
    @Override
    public void serviceUpdate(ServiceEvent event) {
        
        // Insert log message from event.
        if (LogService.LOG_MESSAGE.equals(event.getType())) {
            String logMessage = (String) event.getTarget();
            insertLogMessage(logMessage + "\n");
        }
    } 
    
    /**
     * Inserts a log message line to display.
     * @param logMessage the log message string.
     */
    void insertLogMessage(String logMessage) {
        try {
            textDoc.insertString(textDoc.getLength(), logMessage, null);
            
            // If number of lines exceeds maximum, remove first line.
            Element rootElement = textDoc.getDefaultRootElement();
            if (rootElement.getElementCount() > MAX_LINES_DISPLAYED) {
                int endLineIndex = rootElement.getElement(0).getEndOffset();
                if (endLineIndex >= 0) textDoc.remove(0, endLineIndex);
            }
            
            scrollPanelToBottom();
        }
        catch (BadLocationException e) {
            e.printStackTrace(System.err);
        }
    }
    
    /**
     * Scrolls the vertical scroll bar to the bottom.
     */
    private void scrollPanelToBottom() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                scrollPanel.getVerticalScrollBar().setValue(
                        scrollPanel.getVerticalScrollBar().getMaximum());
            }
        });
    }
}